import {Component, Input, OnInit} from '@angular/core';
import Map from 'ol/Map';
import GeoJSON from 'ol/format/GeoJSON';
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer';
import {OSM, Vector as VectorSource} from 'ol/source';
import {Circle as CircleStyle, Fill, Stroke, Style, Text} from 'ol/style';
import {fromLonLat} from 'ol/proj.js';
import {transform} from 'ol/proj';
import {UtilComponent} from '../../interface/util-component.interface'; // 坐标系转换
@Component({
    selector: 'kylin-vector-label',
    templateUrl: './vector-label.component.html',
    styleUrls: ['./vector-label.component.css']
})
export class VectorLabelComponent implements OnInit, UtilComponent {
   // ---------- 接口实现 begin -------------- //
    hasContent = true;
    map: Map;

    @Input() set data(val) {
        Object.assign(this, val);
    };
    // ---------- 接口实现 end ---------------- //

    openSansAdded = false;
    vectorPolygons: any;
    vectorPoints: any;
    vectorLines: any;
    tileLayer: any;

    myVectorDom = {
        points: {
            text: document.getElementById('points-text'),
            align: document.getElementById('points-align'),
            baseline: document.getElementById('points-baseline'),
            rotation: document.getElementById('points-rotation'),
            font: document.getElementById('points-font'),
            weight: document.getElementById('points-weight'),
            size: document.getElementById('points-size'),
            offsetX: document.getElementById('points-offset-x'),
            offsetY: document.getElementById('points-offset-y'),
            color: document.getElementById('points-color'),
            outline: document.getElementById('points-outline'),
            outlineWidth: document.getElementById('points-outline-width'),
            maxreso: document.getElementById('points-maxreso')
        },
        lines: {
            text: document.getElementById('lines-text'),
            align: document.getElementById('lines-align'),
            baseline: document.getElementById('lines-baseline'),
            rotation: document.getElementById('lines-rotation'),
            font: document.getElementById('lines-font'),
            weight: document.getElementById('lines-weight'),
            placement: document.getElementById('lines-placement'),
            maxangle: document.getElementById('lines-maxangle'),
            overflow: document.getElementById('lines-overflow'),
            size: document.getElementById('lines-size'),
            offsetX: document.getElementById('lines-offset-x'),
            offsetY: document.getElementById('lines-offset-y'),
            color: document.getElementById('lines-color'),
            outline: document.getElementById('lines-outline'),
            outlineWidth: document.getElementById('lines-outline-width'),
            maxreso: document.getElementById('lines-maxreso')
        },
        polygons: {
            text: document.getElementById('polygons-text'),
            align: document.getElementById('polygons-align'),
            baseline: document.getElementById('polygons-baseline'),
            rotation: document.getElementById('polygons-rotation'),
            font: document.getElementById('polygons-font'),
            weight: document.getElementById('polygons-weight'),
            placement: document.getElementById('polygons-placement'),
            maxangle: document.getElementById('polygons-maxangle'),
            overflow: document.getElementById('polygons-overflow'),
            size: document.getElementById('polygons-size'),
            offsetX: document.getElementById('polygons-offset-x'),
            offsetY: document.getElementById('polygons-offset-y'),
            color: document.getElementById('polygons-color'),
            outline: document.getElementById('polygons-outline'),
            outlineWidth: document.getElementById('polygons-outline-width'),
            maxreso: document.getElementById('polygons-maxreso')
        }
    };
    constructor() {
    }

    ngOnInit() {
        this.init();
    }

    init() {
        const center: any = transform([-8161939, 6095025], 'EPSG:3857', 'EPSG:3857')
        this.map.getView().setCenter(center);
        this.map.getView().setZoom(8);
        this.map.getView().setProperties({projection: 'EPSG:3857'}, false);
        this.tileLayer =  new TileLayer({
            source: new OSM()
        });
        this.vectorPoints = new VectorLayer({
            source: new VectorSource({
                url: './assets/data/geojson/point-samples.json',
                format: new GeoJSON()
            }),
            style: this.pointStyleFunction
        });
        this.vectorLines = new VectorLayer({
            source: new VectorSource({
                url: './assets/data/geojson/line-samples.json',
                format: new GeoJSON()
            }),
            style: this.lineStyleFunction
        });
        this.vectorPolygons = new VectorLayer({
            source: new VectorSource({
                url: './assets/data/geojson/polygon-samples.json',
                format: new GeoJSON()
            }),
            style: this.polygonStyleFunction
        });
        this.map.addLayer(this.tileLayer);
        this.map.addLayer(this.vectorPolygons);
        this.map.addLayer(this.vectorLines);
        this.map.addLayer(this.vectorPoints)
    }

    cancel(options?: any): any {
        this.map.removeLayer(this.vectorPolygons);
        this.map.removeLayer(this.vectorPoints);
        this.map.removeLayer(this.vectorLines);
        this.map.removeLayer(this.tileLayer);
    }

    polygonStyleFunction(feature, resolution) {
        return new Style({
            stroke: new Stroke({
                color: 'blue',
                width: 1
            }),
            fill: new Fill({
                color: 'rgba(0, 0, 255, 0.1)'
            }),
            text: this.createTextStyle(feature, resolution, this.myVectorDom.polygons)
        });
    }

    lineStyleFunction(feature, resolution) {
        return new Style({
            stroke: new Stroke({
                color: 'green',
                width: 2
            }),
            text: this.createTextStyle(feature, resolution, this.myVectorDom.lines)
        });
    }

    pointStyleFunction(feature, resolution) {
        return new Style({
            image: new CircleStyle({
                radius: 10,
                fill: new Fill({color: 'rgba(255, 0, 0, 0.1)'}),
                stroke: new Stroke({color: 'red', width: 1})
            }),
            text: this.createTextStyle(feature, resolution, this.myVectorDom.points)
        });
    }

    createTextStyle (feature, resolution, dom)  {
        const align = dom.align.value;
        const baseline = dom.baseline.value;
        const size = dom.size.value;
        const offsetX = parseInt(dom.offsetX.value, 10);
        const offsetY = parseInt(dom.offsetY.value, 10);
        const weight = dom.weight.value;
        const placement = dom.placement ? dom.placement.value : undefined;
        const maxAngle = dom.maxangle ? parseFloat(dom.maxangle.value) : undefined;
        const overflow = dom.overflow ? (dom.overflow.value === 'true') : undefined;
        const rotation = parseFloat(dom.rotation.value);
        if (dom.font.value === '\'Open Sans\'' && !this.openSansAdded) {
            const openSans = document.createElement('link');
            openSans.href = 'https://fonts.googleapis.com/css?family=Open+Sans';
            openSans.rel = 'stylesheet';
            document.getElementsByTagName('head')[0].appendChild(openSans);
            this.openSansAdded = true;
        }
        const font = weight + ' ' + size + ' ' + dom.font.value;
        const fillColor = dom.color.value;
        const outlineColor = dom.outline.value;
        const outlineWidth = parseInt(dom.outlineWidth.value, 10);

        return new Text({
            textAlign: align === '' ? undefined : align,
            textBaseline: baseline,
            font: font,
            text: this.getText(feature, resolution, dom),
            fill: new Fill({color: fillColor}),
            stroke: new Stroke({color: outlineColor, width: outlineWidth}),
            offsetX: offsetX,
            offsetY: offsetY,
            placement: placement,
            maxAngle: maxAngle,
            overflow: overflow,
            rotation: rotation
        });
    };

    getText(feature, resolution, dom) {
        const type = dom.text.value;
        const maxResolution = dom.maxreso.value;
        let text = feature.get('name');

        if (resolution > maxResolution) {
            text = '';
        } else if (type === 'hide') {
            text = '';
        } else if (type === 'shorten') {
            text = text.trunc(12);
        } else if (type === 'wrap' && (!dom.placement || dom.placement.value !== 'line')) {
            text = this.stringDivider(text, 16, '\n');
        }
        return text;
    };

    points() {
        this.vectorPoints.setStyle(this.pointStyleFunction);
    }

    lines() {
        this.vectorLines.setStyle(this.lineStyleFunction);
    }

    polygons() {
        this.vectorPolygons.setStyle(this.polygonStyleFunction);
    }

    stringDivider(str, width, spaceReplacer) {
        if (str.length > width) {
            let p = width;
            while (p > 0 && (str[p] !== ' ' && str[p] !== '-')) {
                p--;
            }
            if (p > 0) {
                let left;
                if (str.substring(p, p + 1) === '-') {
                    left = str.substring(0, p + 1);
                } else {
                    left = str.substring(0, p);
                }
                const right = str.substring(p + 1);
                return left + spaceReplacer + this.stringDivider(right, width, spaceReplacer);
            }
        }
        return str;
    }
}
